module memory_module

contains

  subroutine allocate_all_ids()
    use particle_data
    implicit none

    if(allocated(ParticleIDs%Type0)) deallocate(ParticleIDs%Type0)
    allocate(ParticleIDs%Type0(0:NumPart_Total_AllSnaps(0)-1))
    if(.not.(allocated(ParticleIDs%Type0))) call abort("unable to allocate ParticleIDs%Type0")

    if(allocated(ParticleIDs%Type1)) deallocate(ParticleIDs%Type1)
    allocate(ParticleIDs%Type1(0:NumPart_Total_AllSnaps(1)-1))
    if(.not.(allocated(ParticleIDs%Type1))) call abort("unable to allocate ParticleIDs%Type1")

    if(allocated(ParticleIDs%Type2)) deallocate(ParticleIDs%Type2)
    allocate(ParticleIDs%Type2(0:NumPart_Total_AllSnaps(2)-1))
    if(.not.(allocated(ParticleIDs%Type2))) call abort("unable to allocate ParticleIDs%Type2")

    if(allocated(ParticleIDs%Type3)) deallocate(ParticleIDs%Type3)
    allocate(ParticleIDs%Type3(0:NumPart_Total_AllSnaps(3)-1))
    if(.not.(allocated(ParticleIDs%Type3))) call abort("unable to allocate ParticleIDs%Type3")

    if(allocated(ParticleIDs%Type4)) deallocate(ParticleIDs%Type4)
    allocate(ParticleIDs%Type4(0:NumPart_Total_AllSnaps(4)-1))
    if(.not.(allocated(ParticleIDs%Type4))) call abort("unable to allocate ParticleIDs%Type4")

    if(allocated(ParticleIDs%Type5)) deallocate(ParticleIDs%Type5)
    allocate(ParticleIDs%Type5(0:NumPart_Total_AllSnaps(5)-1))
    if(.not.(allocated(ParticleIDs%Type5))) call abort("unable to allocate ParticleIDs%Type5")

    if(allocated(IndexIDs%Type0)) deallocate(IndexIDs%Type0)
    allocate(IndexIDs%Type0(0:NumPart_Total_AllSnaps(0)-1))
    if(.not.(allocated(IndexIDs%Type0))) call abort("unable to allocate IndexIDs%Type0")

    if(allocated(IndexIDs%Type1)) deallocate(IndexIDs%Type1)
    allocate(IndexIDs%Type1(0:NumPart_Total_AllSnaps(1)-1))
    if(.not.(allocated(IndexIDs%Type1))) call abort("unable to allocate IndexIDs%Type1")

    if(allocated(IndexIDs%Type2)) deallocate(IndexIDs%Type2)
    allocate(IndexIDs%Type2(0:NumPart_Total_AllSnaps(2)-1))
    if(.not.(allocated(IndexIDs%Type2))) call abort("unable to allocate IndexIDs%Type2")

    if(allocated(IndexIDs%Type3)) deallocate(IndexIDs%Type3)
    allocate(IndexIDs%Type3(0:NumPart_Total_AllSnaps(3)-1))
    if(.not.(allocated(IndexIDs%Type3))) call abort("unable to allocate IndexIDs%Type3")

    if(allocated(IndexIDs%Type4)) deallocate(IndexIDs%Type4)
    allocate(IndexIDs%Type4(0:NumPart_Total_AllSnaps(4)-1))
    if(.not.(allocated(IndexIDs%Type4))) call abort("unable to allocate IndexIDs%Type4")

    if(allocated(IndexIDs%Type5)) deallocate(IndexIDs%Type5)
    allocate(IndexIDs%Type5(0:NumPart_Total_AllSnaps(5)-1))
    if(.not.(allocated(IndexIDs%Type5))) call abort("unable to allocate IndexIDs%Type5")

    if(allocated(UniqueCoordinates%Type0)) deallocate(UniqueCoordinates%Type0)
    allocate(UniqueCoordinates%Type0(0:2,0:NumPart_Total_AllSnaps(0)-1))
    if(.not.(allocated(UniqueCoordinates%Type0))) call abort("unable to allocate UniqueCoordinates%Type0")

    if(allocated(UniqueCoordinates%Type1)) deallocate(UniqueCoordinates%Type1)
    allocate(UniqueCoordinates%Type1(0:2,0:NumPart_Total_AllSnaps(1)-1))
    if(.not.(allocated(UniqueCoordinates%Type1))) call abort("unable to allocate UniqueCoordinates%Type1")

    if(allocated(UniqueCoordinates%Type2)) deallocate(UniqueCoordinates%Type2)
    allocate(UniqueCoordinates%Type2(0:2,0:NumPart_Total_AllSnaps(2)-1))
    if(.not.(allocated(UniqueCoordinates%Type2))) call abort("unable to allocate UniqueCoordinates%Type2")

    if(allocated(UniqueCoordinates%Type3)) deallocate(UniqueCoordinates%Type3)
    allocate(UniqueCoordinates%Type3(0:2,0:NumPart_Total_AllSnaps(3)-1))
    if(.not.(allocated(UniqueCoordinates%Type3))) call abort("unable to allocate UniqueCoordinates%Type3")

    if(allocated(UniqueCoordinates%Type4)) deallocate(UniqueCoordinates%Type4)
    allocate(UniqueCoordinates%Type4(0:2,0:NumPart_Total_AllSnaps(4)-1))
    if(.not.(allocated(UniqueCoordinates%Type4))) call abort("unable to allocate UniqueCoordinates%Type4")

    if(allocated(UniqueCoordinates%Type5)) deallocate(UniqueCoordinates%Type5)
    allocate(UniqueCoordinates%Type5(0:2,0:NumPart_Total_AllSnaps(5)-1))
    if(.not.(allocated(UniqueCoordinates%Type5))) call abort("unable to allocate UniqueCoordinates%Type5")

    if(allocated(ForceFreeCoordinates%Type0)) deallocate(ForceFreeCoordinates%Type0)
    allocate(ForceFreeCoordinates%Type0(0:2,0:NumPart_Total_AllSnaps(0)-1))
    if(.not.(allocated(ForceFreeCoordinates%Type0))) call abort("unable to allocate ForceFreeCoordinates%Type0")

    if(allocated(ForceFreeCoordinates%Type1)) deallocate(ForceFreeCoordinates%Type1)
    allocate(ForceFreeCoordinates%Type1(0:2,0:NumPart_Total_AllSnaps(1)-1))
    if(.not.(allocated(ForceFreeCoordinates%Type1))) call abort("unable to allocate ForceFreeCoordinates%Type1")

    if(allocated(ForceFreeCoordinates%Type2)) deallocate(ForceFreeCoordinates%Type2)
    allocate(ForceFreeCoordinates%Type2(0:2,0:NumPart_Total_AllSnaps(2)-1))
    if(.not.(allocated(ForceFreeCoordinates%Type2))) call abort("unable to allocate ForceFreeCoordinates%Type2")

    if(allocated(ForceFreeCoordinates%Type3)) deallocate(ForceFreeCoordinates%Type3)
    allocate(ForceFreeCoordinates%Type3(0:2,0:NumPart_Total_AllSnaps(3)-1))
    if(.not.(allocated(ForceFreeCoordinates%Type3))) call abort("unable to allocate ForceFreeCoordinates%Type3")

    if(allocated(ForceFreeCoordinates%Type4)) deallocate(ForceFreeCoordinates%Type4)
    allocate(ForceFreeCoordinates%Type4(0:2,0:NumPart_Total_AllSnaps(4)-1))
    if(.not.(allocated(ForceFreeCoordinates%Type4))) call abort("unable to allocate ForceFreeCoordinates%Type4")

    if(allocated(ForceFreeCoordinates%Type5)) deallocate(ForceFreeCoordinates%Type5)
    allocate(ForceFreeCoordinates%Type5(0:2,0:NumPart_Total_AllSnaps(5)-1))
    if(.not.(allocated(ForceFreeCoordinates%Type5))) call abort("unable to allocate ForceFreeCoordinates%Type5")

    if(allocated(UniqueVelocity%Type0)) deallocate(UniqueVelocity%Type0)
    allocate(UniqueVelocity%Type0(0:2,0:NumPart_Total_AllSnaps(0)-1))
    if(.not.(allocated(UniqueVelocity%Type0))) call abort("unable to allocate UniqueVelocity%Type0")

    if(allocated(UniqueVelocity%Type1)) deallocate(UniqueVelocity%Type1)
    allocate(UniqueVelocity%Type1(0:2,0:NumPart_Total_AllSnaps(1)-1))
    if(.not.(allocated(UniqueVelocity%Type1))) call abort("unable to allocate UniqueVelocity%Type1")

    if(allocated(UniqueVelocity%Type2)) deallocate(UniqueVelocity%Type2)
    allocate(UniqueVelocity%Type2(0:2,0:NumPart_Total_AllSnaps(2)-1))
    if(.not.(allocated(UniqueVelocity%Type2))) call abort("unable to allocate UniqueVelocity%Type2")

    if(allocated(UniqueVelocity%Type3)) deallocate(UniqueVelocity%Type3)
    allocate(UniqueVelocity%Type3(0:2,0:NumPart_Total_AllSnaps(3)-1))
    if(.not.(allocated(UniqueVelocity%Type3))) call abort("unable to allocate UniqueVelocity%Type3")

    if(allocated(UniqueVelocity%Type4)) deallocate(UniqueVelocity%Type4)
    allocate(UniqueVelocity%Type4(0:2,0:NumPart_Total_AllSnaps(4)-1))
    if(.not.(allocated(UniqueVelocity%Type4))) call abort("unable to allocate UniqueVelocity%Type4")

    if(allocated(UniqueVelocity%Type5)) deallocate(UniqueVelocity%Type5)
    allocate(UniqueVelocity%Type5(0:2,0:NumPart_Total_AllSnaps(5)-1))
    if(.not.(allocated(UniqueVelocity%Type5))) call abort("unable to allocate UniqueVelocity%Type5")

    if(allocated(UniqueIDs%Type0)) deallocate(UniqueIDs%Type0)
    allocate(UniqueIDs%Type0(0:NumPart_Total_AllSnaps(0)-1))
    if(.not.(allocated(UniqueIDs%Type0))) call abort("unable to allocate UniqueIDs%Type0")

    if(allocated(UniqueIDs%Type1)) deallocate(UniqueIDs%Type1)
    allocate(UniqueIDs%Type1(0:NumPart_Total_AllSnaps(1)-1))
    if(.not.(allocated(UniqueIDs%Type1))) call abort("unable to allocate UniqueIDs%Type1")

    if(allocated(UniqueIDs%Type2)) deallocate(UniqueIDs%Type2)
    allocate(UniqueIDs%Type2(0:NumPart_Total_AllSnaps(2)-1))
    if(.not.(allocated(UniqueIDs%Type2))) call abort("unable to allocate UniqueIDs%Type2")

    if(allocated(UniqueIDs%Type3)) deallocate(UniqueIDs%Type3)
    allocate(UniqueIDs%Type3(0:NumPart_Total_AllSnaps(3)-1))
    if(.not.(allocated(UniqueIDs%Type3))) call abort("unable to allocate UniqueIDs%Type3")

    if(allocated(UniqueIDs%Type4)) deallocate(UniqueIDs%Type4)
    allocate(UniqueIDs%Type4(0:NumPart_Total_AllSnaps(4)-1))
    if(.not.(allocated(UniqueIDs%Type4))) call abort("unable to allocate UniqueIDs%Type4")

    if(allocated(UniqueIDs%Type5)) deallocate(UniqueIDs%Type5)
    allocate(UniqueIDs%Type5(0:NumPart_Total_AllSnaps(5)-1))
    if(.not.(allocated(UniqueIDs%Type5))) call abort("unable to allocate UniqueIDs%Type5")

    if(allocated(SnapIDs%Type0)) deallocate(SnapIDs%Type0)
    allocate(SnapIDs%Type0(0:NumPart_Total_AllSnaps(0)-1))
    if(.not.(allocated(SnapIDs%Type0))) call abort("unable to allocate SnapIDs%Type0")

    if(allocated(SnapIDs%Type1)) deallocate(SnapIDs%Type1)
    allocate(SnapIDs%Type1(0:NumPart_Total_AllSnaps(1)-1))
    if(.not.(allocated(SnapIDs%Type1))) call abort("unable to allocate SnapIDs%Type1")

    if(allocated(SnapIDs%Type2)) deallocate(SnapIDs%Type2)
    allocate(SnapIDs%Type2(0:NumPart_Total_AllSnaps(2)-1))
    if(.not.(allocated(SnapIDs%Type2))) call abort("unable to allocate SnapIDs%Type2")

    if(allocated(SnapIDs%Type3)) deallocate(SnapIDs%Type3)
    allocate(SnapIDs%Type3(0:NumPart_Total_AllSnaps(3)-1))
    if(.not.(allocated(SnapIDs%Type3))) call abort("unable to allocate SnapIDs%Type3")

    if(allocated(SnapIDs%Type4)) deallocate(SnapIDs%Type4)
    allocate(SnapIDs%Type4(0:NumPart_Total_AllSnaps(4)-1))
    if(.not.(allocated(SnapIDs%Type4))) call abort("unable to allocate SnapIDs%Type4")

    if(allocated(SnapIDs%Type5)) deallocate(SnapIDs%Type5)
    allocate(SnapIDs%Type5(0:NumPart_Total_AllSnaps(5)-1))
    if(.not.(allocated(SnapIDs%Type5))) call abort("unable to allocate SnapIDs%Type5")

    if(allocated(UniqueSnapIDs%Type0)) deallocate(UniqueSnapIDs%Type0)
    allocate(UniqueSnapIDs%Type0(0:NumPart_Total_AllSnaps(0)-1))
    if(.not.(allocated(UniqueSnapIDs%Type0))) call abort("unable to allocate UniqueSnapIDs%Type0")

    if(allocated(UniqueSnapIDs%Type1)) deallocate(UniqueSnapIDs%Type1)
    allocate(UniqueSnapIDs%Type1(0:NumPart_Total_AllSnaps(1)-1))
    if(.not.(allocated(UniqueSnapIDs%Type1))) call abort("unable to allocate UniqueSnapIDs%Type1")

    if(allocated(UniqueSnapIDs%Type2)) deallocate(UniqueSnapIDs%Type2)
    allocate(UniqueSnapIDs%Type2(0:NumPart_Total_AllSnaps(2)-1))
    if(.not.(allocated(UniqueSnapIDs%Type2))) call abort("unable to allocate UniqueSnapIDs%Type2")

    if(allocated(UniqueSnapIDs%Type3)) deallocate(UniqueSnapIDs%Type3)
    allocate(UniqueSnapIDs%Type3(0:NumPart_Total_AllSnaps(3)-1))
    if(.not.(allocated(UniqueSnapIDs%Type3))) call abort("unable to allocate UniqueSnapIDs%Type3")

    if(allocated(UniqueSnapIDs%Type4)) deallocate(UniqueSnapIDs%Type4)
    allocate(UniqueSnapIDs%Type4(0:NumPart_Total_AllSnaps(4)-1))
    if(.not.(allocated(UniqueSnapIDs%Type4))) call abort("unable to allocate UniqueSnapIDs%Type4")

    if(allocated(UniqueSnapIDs%Type5)) deallocate(UniqueSnapIDs%Type5)
    allocate(UniqueSnapIDs%Type5(0:NumPart_Total_AllSnaps(5)-1))
    if(.not.(allocated(UniqueSnapIDs%Type5))) call abort("unable to allocate UniqueSnapIDs%Type5")


  end subroutine allocate_all_ids


 subroutine allocate_ics_particles()
    use ic_data
    implicit none

    if(allocated(IC_Coordinates%Type0)) deallocate(IC_Coordinates%Type0)
    allocate(IC_Coordinates%Type0(0:2,0:NumPart_ICs(0)-1))
    if(.not.(allocated(IC_Coordinates%Type0))) call abort("unable to allocate IC_Coordinates%Type0")

    if(allocated(IC_Velocity%Type0)) deallocate(IC_Velocity%Type0)
    allocate(IC_Velocity%Type0(0:2,0:NumPart_ICs(0)-1))
    if(.not.(allocated(IC_Velocity%Type0))) call abort("unable to allocate IC_Velocity%Type0")

    if(allocated(IC_ParticleIDs%Type0)) deallocate(IC_ParticleIDs%Type0)
    allocate(IC_ParticleIDs%Type0(0:NumPart_ICs(0)-1))
    if(.not.(allocated(IC_ParticleIDs%Type0))) call abort("unable to allocate IC_ParticleIDs%Type0")

    if(allocated(IC_IndexIDs%Type0)) deallocate(IC_IndexIDs%Type0)
    allocate(IC_IndexIDs%Type0(0:NumPart_ICs(0)-1))
    if(.not.(allocated(IC_IndexIDs%Type0))) call abort("unable to allocate IC_IndexIDs%Type0")

    if(allocated(IC_Coordinates%Type1)) deallocate(IC_Coordinates%Type1)
    allocate(IC_Coordinates%Type1(0:2,0:NumPart_ICs(1)-1))
    if(.not.(allocated(IC_Coordinates%Type1))) call abort("unable to allocate IC_Coordinates%Type1")

    if(allocated(IC_Velocity%Type1)) deallocate(IC_Velocity%Type1)
    allocate(IC_Velocity%Type1(0:2,0:NumPart_ICs(1)-1))
    if(.not.(allocated(IC_Velocity%Type1))) call abort("unable to allocate IC_Velocity%Type1")

    if(allocated(IC_ParticleIDs%Type1)) deallocate(IC_ParticleIDs%Type1)
    allocate(IC_ParticleIDs%Type1(0:NumPart_ICs(1)-1))
    if(.not.(allocated(IC_ParticleIDs%Type1))) call abort("unable to allocate IC_ParticleIDs%Type1")

    if(allocated(IC_IndexIDs%Type1)) deallocate(IC_IndexIDs%Type1)
    allocate(IC_IndexIDs%Type1(0:NumPart_ICs(1)-1))
    if(.not.(allocated(IC_IndexIDs%Type1))) call abort("unable to allocate IC_IndexIDs%Type1")

    if(allocated(IC_Coordinates%Type2)) deallocate(IC_Coordinates%Type2)
    allocate(IC_Coordinates%Type2(0:2,0:NumPart_ICs(2)-1))
    if(.not.(allocated(IC_Coordinates%Type2))) call abort("unable to allocate IC_Coordinates%Type2")

    if(allocated(IC_Velocity%Type2)) deallocate(IC_Velocity%Type2)
    allocate(IC_Velocity%Type2(0:2,0:NumPart_ICs(2)-1))
    if(.not.(allocated(IC_Velocity%Type2))) call abort("unable to allocate IC_Velocity%Type2")

    if(allocated(IC_ParticleIDs%Type2)) deallocate(IC_ParticleIDs%Type2)
    allocate(IC_ParticleIDs%Type2(0:NumPart_ICs(2)-1))
    if(.not.(allocated(IC_ParticleIDs%Type2))) call abort("unable to allocate IC_ParticleIDs%Type2")

    if(allocated(IC_IndexIDs%Type2)) deallocate(IC_IndexIDs%Type2)
    allocate(IC_IndexIDs%Type2(0:NumPart_ICs(2)-1))
    if(.not.(allocated(IC_IndexIDs%Type2))) call abort("unable to allocate IC_IndexIDs%Type2")

    if(allocated(IC_Coordinates%Type3)) deallocate(IC_Coordinates%Type3)
    allocate(IC_Coordinates%Type3(0:2,0:NumPart_ICs(3)-1))
    if(.not.(allocated(IC_Coordinates%Type3))) call abort("unable to allocate IC_Coordinates%Type3")

    if(allocated(IC_Velocity%Type3)) deallocate(IC_Velocity%Type3)
    allocate(IC_Velocity%Type3(0:2,0:NumPart_ICs(3)-1))
    if(.not.(allocated(IC_Velocity%Type3))) call abort("unable to allocate IC_Velocity%Type3")

    if(allocated(IC_ParticleIDs%Type3)) deallocate(IC_ParticleIDs%Type3)
    allocate(IC_ParticleIDs%Type3(0:NumPart_ICs(3)-1))
    if(.not.(allocated(IC_ParticleIDs%Type3))) call abort("unable to allocate IC_ParticleIDs%Type3")

    if(allocated(IC_IndexIDs%Type3)) deallocate(IC_IndexIDs%Type3)
    allocate(IC_IndexIDs%Type3(0:NumPart_ICs(3)-1))
    if(.not.(allocated(IC_IndexIDs%Type3))) call abort("unable to allocate IC_IndexIDs%Type3")

    if(allocated(IC_Coordinates%Type4)) deallocate(IC_Coordinates%Type4)
    allocate(IC_Coordinates%Type4(0:2,0:NumPart_ICs(4)-1))
    if(.not.(allocated(IC_Coordinates%Type4))) call abort("unable to allocate IC_Coordinates%Type4")

    if(allocated(IC_Velocity%Type4)) deallocate(IC_Velocity%Type4)
    allocate(IC_Velocity%Type4(0:2,0:NumPart_ICs(4)-1))
    if(.not.(allocated(IC_Velocity%Type4))) call abort("unable to allocate IC_Velocity%Type4")

    if(allocated(IC_ParticleIDs%Type4)) deallocate(IC_ParticleIDs%Type4)
    allocate(IC_ParticleIDs%Type4(0:NumPart_ICs(4)-1))
    if(.not.(allocated(IC_ParticleIDs%Type4))) call abort("unable to allocate IC_ParticleIDs%Type4")

    if(allocated(IC_IndexIDs%Type4)) deallocate(IC_IndexIDs%Type4)
    allocate(IC_IndexIDs%Type4(0:NumPart_ICs(4)-1))
    if(.not.(allocated(IC_IndexIDs%Type4))) call abort("unable to allocate IC_IndexIDs%Type4")

    if(allocated(IC_Coordinates%Type5)) deallocate(IC_Coordinates%Type5)
    allocate(IC_Coordinates%Type5(0:2,0:NumPart_ICs(5)-1))
    if(.not.(allocated(IC_Coordinates%Type5))) call abort("unable to allocate IC_Coordinates%Type5")

    if(allocated(IC_Velocity%Type5)) deallocate(IC_Velocity%Type5)
    allocate(IC_Velocity%Type5(0:2,0:NumPart_ICs(5)-1))
    if(.not.(allocated(IC_Velocity%Type5))) call abort("unable to allocate IC_Velocity%Type5")

    if(allocated(IC_ParticleIDs%Type5)) deallocate(IC_ParticleIDs%Type5)
    allocate(IC_ParticleIDs%Type5(0:NumPart_ICs(5)-1))
    if(.not.(allocated(IC_ParticleIDs%Type5))) call abort("unable to allocate IC_ParticleIDs%Type5")

    if(allocated(IC_IndexIDs%Type5)) deallocate(IC_IndexIDs%Type5)
    allocate(IC_IndexIDs%Type5(0:NumPart_ICs(5)-1))
    if(.not.(allocated(IC_IndexIDs%Type5))) call abort("unable to allocate IC_IndexIDs%Type5")

  end subroutine allocate_ics_particles

end module memory_module
